package com.zmj.sy.mom.srv.aps.service;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zmj.sy.mom.srv.aps.bean.dto.reportErp.ReportErpLogQureyDto;
import com.zmj.sy.mom.srv.aps.bean.dto.reportErp.ReportErpLogUpdateDto;
import com.zmj.sy.mom.srv.aps.bean.entity.base.BaseEntity;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.WorkRecord;
import com.zmj.sy.mom.srv.aps.bean.entity.order.ApsWorkDetail;
import com.zmj.sy.mom.srv.aps.bean.entity.order.OrderBom;
import com.zmj.sy.mom.srv.aps.bean.entity.order.OrderPhase;
import com.zmj.sy.mom.srv.aps.bean.entity.reportErp.ErpPhaseReport;
import com.zmj.sy.mom.srv.aps.bean.entity.reportErp.NoreportErpConfig;
import com.zmj.sy.mom.srv.aps.bean.entity.reportErp.ReportErpReply;
import com.zmj.sy.mom.srv.aps.bean.vo.reportErp.SysReportErpLogVo;
import com.zmj.sy.mom.srv.aps.feign.ErpApiClient;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.MD5.MD5;
import com.zmj.sy.mom.srv.aps.utils.PkgUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


@RequiredArgsConstructor
@Service
public class ReportErpService {
    private final ReportErpMapper reportErpMapper;
    private final WorkRecordMapper workRecordMapper;
    private final OrderBomMapper orderBomMapper;
    private final OrderPhaseMapper orderPhaseMapper;
    private final ErpApiClient erpApiClient;
    private final ApsWorkDetailMapper apsWorkDetailMapper;
    private final NoreportErpConfigMapper noreportErpConfigMapper;

    @Value("${zmj.sy.send-erp.filter}")
    private String sendErpFilter;

    /**
     * @Description: 报工记录转换为erp回传格式
     *
     * @author: hejiahui
     * @since: 2024/10/8 11:26
     */
    public void changeReportData() {
        //只处理近一周的报工
        String startTime = DateUtil.date().offset(DateField.DAY_OF_MONTH,-7).toString("yyyy-MM-dd HH:mm:ss");
        String endTime = DateUtil.date().toString("yyyy-MM-dd HH:mm:ss");
        this.changeReportData(startTime, endTime);
    }

    /**
     * @Description: 报工记录转换为erp回传格式
     *
     * @author: hejiahui
     * @since: 2024/10/8 11:26
     */
    public void changeReportData(String startTime, String endTime) {
        //锁定当前未成功的报工记录
        workRecordMapper.lambdaUpdate().set(WorkRecord::getErpState, 1)
                .between(WorkRecord::getCreateDateTime, startTime, endTime)
                .ne(WorkRecord::getErpState, 2).ne(WorkRecord::getErpState,1).le(WorkRecord::getErpState, 10)
                .ne(WorkRecord::getPhaseCode, "YC")
                .eq(WorkRecord::getType,2).eq(WorkRecord::getWorkType,2).update();
        //汇总获取锁定后的报工数据
        QueryWrapper<?> reportQuery = new QueryWrapper<>();
        reportQuery.eq("record.type", 2);
        reportQuery.eq("record.work_type", 2);
        reportQuery.eq("record.erp_state", 1);
        reportQuery.ne("record.phase_code", "YC");
        reportQuery.between("record.create_date_time", startTime, endTime);
        List<Map<String, Object>> sumReportMapList = reportErpMapper.getSumReportData(reportQuery);
        if (ObjectUtils.isEmpty(sumReportMapList)) {
            return;
        }
        //获取报工详情
        List<Map<String, Object>> reportDataDetail = reportErpMapper.getReportData(reportQuery);
        Map<String, List<Map<String, Object>>> reportDataDetailMap = reportDataDetail.stream().collect(Collectors.groupingBy(e -> e.get("construct_no").toString() + e.get("seq") + e.get("work_order_code")
                + e.get("plmid") + e.get("erp_code") + e.get("phase_code") + e.get("group_number") + e.get("phase_id")));
        //获取erp数据
        Set<String> construList = sumReportMapList.stream().filter(e -> StringUtils.isNotBlank((String) e.get("construct_no")))
                .map(e -> (String) e.get("construct_no")).collect(Collectors.toSet());
        Set<String> materialCodeList = sumReportMapList.stream().filter(e -> StringUtils.isNotBlank((String) e.get("erp_code")))
                .map(e -> (String) e.get("erp_code")).collect(Collectors.toSet());
        QueryWrapper<?> erpWrapper = new QueryWrapper<>();
        erpWrapper.in("detail.order_code", construList);
        erpWrapper.in("detail.material_code", materialCodeList);
        List<Map<String, Object>> erpDateMapList = reportErpMapper.getErpPhaseMap(erpWrapper);
        Map<String, List<Map<String, Object>>> erpDateMap = erpDateMapList.stream().collect(Collectors.groupingBy(e -> e.get("order_code").toString() + e.get("material_code")
                + e.get("mes_work_phase") + e.get("mes_work_center")));

        //获取父级信息
        Set<String> pidList = sumReportMapList.stream().filter(e -> ObjectUtils.isNotEmpty(e.get("bom_pid"))).map(e -> e.get("bom_pid").toString()).collect(Collectors.toSet());
        List<OrderBom> parentBomList = orderBomMapper.lambdaQuery().in(BaseEntity::getId, pidList).list();
        Map<Integer, List<OrderBom>> parBomListMap = parentBomList.stream().collect(Collectors.groupingBy(BaseEntity::getId));
        //获取原版工序
        Set<Object> phaseId = sumReportMapList.stream().map(e -> e.get("phase_id")).collect(Collectors.toSet());
        List<OrderPhase> phaseIdList = orderPhaseMapper.lambdaQuery().in(BaseEntity::getId, phaseId).list();
        Map<Integer, List<OrderPhase>> phaseIdMap = phaseIdList.stream().collect(Collectors.groupingBy(OrderPhase::getId));
        //获取订单数量
        List<String> woNoList = sumReportMapList.stream().filter(e -> StringUtils.isNotBlank((String) e.get("work_order_code")))
                .map(e -> (String) e.get("work_order_code")).collect(Collectors.toList());
        List<String> pWoNoList = parentBomList.stream().filter(e -> StringUtils.isNotBlank(e.getWorkOrderCode()))
                .map(e -> e.getWorkOrderCode()).collect(Collectors.toList());
        List<String> plmidList = sumReportMapList.stream().filter(e -> StringUtils.isNotBlank((String) e.get("plmid")))
                .map(e -> (String) e.get("plmid")).collect(Collectors.toList());
        List<String> seqList = sumReportMapList.stream().filter(e -> ObjectUtils.isNotEmpty(e.get("seq")))
                .map(e -> e.get("seq").toString()).collect(Collectors.toList());
        QueryWrapper<?> orderQuery = new QueryWrapper<>();
        orderQuery.in("ord.construct_no", construList);
        orderQuery.in("aword.work_order_code", woNoList);
        orderQuery.in(ObjectUtils.isNotEmpty(pWoNoList),"pbom.work_order_code", pWoNoList);
        orderQuery.in("aord.seq", seqList);
        orderQuery.in("bom.plm_id", plmidList);
        List<Map<String, Object>> orderCntList = reportErpMapper.getOrderCntList(orderQuery);
        Map<String, List<Map<String, Object>>> mapList = new HashMap<>();
        if (ObjectUtils.isNotEmpty(orderCntList)) {
            mapList = orderCntList.stream().collect(Collectors.groupingBy(e -> e.get("construct_no").toString() +
                    e.get("seq") + e.get("woNo") + e.get("pWoNo") + e.get("plm_id") + e.get("woId")));
        }
        //配盘工序、预处理工序特殊处理
        Set<Integer> bomIdSet = sumReportMapList.stream().filter(e -> e.get("workChain").toString().contains("PP") && (e.get("phase_code").toString().equals("PZ") || e.get("phase_code").toString().equals("XH")))
                .map(e -> (Integer) e.get("bom_id")).collect(Collectors.toSet());
        Map<Integer, List<OrderPhase>> ppBomIdMap = new HashMap<>();
        if (ObjectUtils.isNotEmpty(bomIdSet)) {
            List<OrderPhase> ppPhaseIdList = orderPhaseMapper.lambdaQuery().in(OrderPhase::getBomId, bomIdSet).eq(OrderPhase::getPhaseCode, "PP").list();
            ppBomIdMap = ppPhaseIdList.stream().collect(Collectors.groupingBy(OrderPhase::getBomId));
        }
        Set<Integer> ycBomIdSet = sumReportMapList.stream().filter(e -> e.get("workChain").toString().contains("YC") && (e.get("phase_code").toString().equals("HG") || e.get("phase_code").toString().equals("JG")))
                .map(e -> (Integer) e.get("bom_id")).collect(Collectors.toSet());
        Map<Integer, List<OrderPhase>> ycBomIdMap = new HashMap<>();
        if (ObjectUtils.isNotEmpty(ycBomIdSet)) {
            List<OrderPhase> ycPhaseIdList = orderPhaseMapper.lambdaQuery().in(OrderPhase::getBomId, ycBomIdSet).eq(OrderPhase::getPhaseCode, "YC").list();
            ycBomIdMap = ycPhaseIdList.stream().collect(Collectors.groupingBy(OrderPhase::getBomId));
        }

        //变更报工记录
        for (Map<String, Object> reportMap : sumReportMapList) {
            //获取报工记录详情
            List<Map<String, Object>> detailList = reportDataDetailMap.get(reportMap.get("construct_no").toString() + reportMap.get("seq") + reportMap.get("work_order_code") + reportMap.get("plmid") + reportMap.get("erp_code") +
                    reportMap.get("phase_code") + reportMap.get("group_number") + reportMap.get("phase_id"));
            if (ObjectUtils.isEmpty(detailList)) {
                continue;
            }
            List<String> recordIds = detailList.stream().map(e -> e.get("id").toString()).collect(Collectors.toList());

            try {
                ReportErpReply erpPhaseReport =  new ReportErpReply();
                BigDecimal cnt = (BigDecimal) reportMap.get("reportCnt");
                erpPhaseReport.setAddQty(cnt.intValue() );
                erpPhaseReport.setPlmid((String) reportMap.get("plmid"));
                erpPhaseReport.setPartName((String) reportMap.get("mater_name"));
                erpPhaseReport.setPhase((String) reportMap.get("phase_code"));
                erpPhaseReport.setEmployeeCode("007605");
                erpPhaseReport.setFactory("100");
                erpPhaseReport.setMaterialCode((String) reportMap.get("erp_code"));
                erpPhaseReport.setNgQty(0);
                erpPhaseReport.setOkQty(cnt.intValue());
                erpPhaseReport.setOrderCode((String) reportMap.get("construct_no"));
                erpPhaseReport.setTaskCode(PkgUtils.gen((Integer) reportMap.get("seq")));
                erpPhaseReport.setWorkEndTime(reportMap.get("reportTime").toString());
                erpPhaseReport.setWorkStartTime(reportMap.get("startTime").toString());
                erpPhaseReport.setWorkOrderCode((String) reportMap.get("work_order_code"));
                erpPhaseReport.setWorkPlace((String) reportMap.get("group_number"));
                erpPhaseReport.setWoId((Integer) reportMap.get("woId"));
                //获取原版工序
                List<OrderPhase> orderPhases = phaseIdMap.get((Integer) reportMap.get("phase_id"));
                if (ObjectUtils.isEmpty(orderPhases)) {
                    throw new Exception("原版工序缺失！" + reportMap);
                }
                OrderPhase orderPhase = orderPhases.get(0);
                //erp数据映射
                String phaseCode = orderPhase.getPhaseCode();
                Integer phaseSeq = 0;
                if (Character.isDigit(phaseCode.charAt(phaseCode.length()-2)) && Character.isDigit(phaseCode.charAt(phaseCode.length()-1))) {
                    phaseSeq = Integer.parseInt(phaseCode.substring(phaseCode.length()-2));
                    phaseCode = phaseCode.substring(0, phaseCode.length() - 2);
                }
                List<Map<String, Object>> erpDateMaps = erpDateMap.get(reportMap.get("construct_no").toString() + reportMap.get("erp_code").toString() + phaseCode + orderPhase.getWorkGroupNumber());
                if (ObjectUtils.isEmpty(erpDateMaps)) {
                    throw new Exception("erp数据映射缺失！" + reportMap);
                }
//                Map<String, Object> erpMap = erpDateMaps.get(0);
                Map<String, Object> erpMap = new HashMap<>();
                try {
                    erpMap = this.getByPhaseSeq(erpDateMaps, phaseSeq);
                } catch (Exception e) {
                    erpMap = erpDateMaps.get(0);
                }
                erpPhaseReport.setOpSeq(erpMap.get("seq").toString());
                erpPhaseReport.setMaterialName((String) reportMap.get("mater_name"));
                erpPhaseReport.setOpCode(erpMap.get("op_code").toString());
                erpPhaseReport.setOpName(erpMap.get("op_name").toString());
                erpPhaseReport.setOp(erpMap.get("op").toString());
                erpPhaseReport.setOkId("N");
                erpPhaseReport.setUpdateDate(DateUtil.date().toString());
                erpPhaseReport.setCreateDate(DateUtil.date().toString());
                erpPhaseReport.setReportTimes(0);
                erpPhaseReport.setFlag(-1);
                erpPhaseReport.setDeleted(0);
                //获取父级
                List<OrderBom> bomPid = parBomListMap.get((Integer)reportMap.get("bom_pid"));
                if (ObjectUtils.isEmpty(bomPid)) {
                    erpPhaseReport.setWorkOrderParent("");
                }else {
                    erpPhaseReport.setWorkOrderParent(bomPid.get(0).getWorkOrderCode());
                }
                //获取订单数量
                List<Map<String, Object>> cntList = mapList.get((String)reportMap.get("construct_no") + reportMap.get("seq") + reportMap.get("work_order_code") + erpPhaseReport.getWorkOrderParent() + reportMap.get("plmid") + reportMap.get("woId"));
                if (ObjectUtils.isNotEmpty(cntList)) {
                    Integer totalCnt = new BigDecimal(cntList.get(0).get("totalCnt").toString()).intValue();
                    erpPhaseReport.setOrderCnt(totalCnt);
                }
                //配盘工序特殊处理
                if (reportMap.get("workChain").toString().contains("PP") && (reportMap.get("phase_code").toString().equals("PZ") || reportMap.get("phase_code").toString().equals("XH"))) {
                    ReportErpReply ppErpPhaseReport =  new ReportErpReply();
                    BeanUtils.copyProperties(erpPhaseReport, ppErpPhaseReport);
                    ppErpPhaseReport.setPhase("PP");
                    List<OrderPhase> ppPhases = ppBomIdMap.get((Integer) reportMap.get("bom_id"));
                    if (ObjectUtils.isNotEmpty(ppPhases)) {
                        OrderPhase ppPhase = ppPhases.get(0);
                        List<Map<String, Object>> ppErpDateMaps = erpDateMap.get(reportMap.get("construct_no").toString() + reportMap.get("erp_code").toString() + ppPhase.getPhaseCode() + ppPhase.getWorkGroupNumber());
                        if (ObjectUtils.isNotEmpty(ppErpDateMaps)) {
                            Map<String, Object> ppErpPhase = ppErpDateMaps.get(0);
                            ppErpPhaseReport.setWorkPlace(ppPhase.getWorkGroupNumber());
                            ppErpPhaseReport.setOpSeq(ppErpPhase.get("seq").toString());
                            ppErpPhaseReport.setOpCode(ppErpPhase.get("op_code").toString());
                            ppErpPhaseReport.setOpName(ppErpPhase.get("op_name").toString());
                            ppErpPhaseReport.setOp(ppErpPhase.get("op").toString());
                            reportErpMapper.insert(ppErpPhaseReport);
                        }
                    }
                }
                //预处理工序特殊处理
                if (reportMap.get("workChain").toString().contains("YC") && (reportMap.get("phase_code").toString().equals("HG") || reportMap.get("phase_code").toString().equals("JG"))) {
                    ReportErpReply ycErpPhaseReport =  new ReportErpReply();
                    BeanUtils.copyProperties(erpPhaseReport, ycErpPhaseReport);
                    ycErpPhaseReport.setPhase("YC");
                    List<OrderPhase> ycPhases = ycBomIdMap.get((Integer) reportMap.get("bom_id"));
                    if (ObjectUtils.isNotEmpty(ycPhases)) {
                        OrderPhase ycPhase = ycPhases.get(0);
                        List<Map<String, Object>> ycErpDateMaps = erpDateMap.get(reportMap.get("construct_no").toString() + reportMap.get("erp_code").toString() + ycPhase.getPhaseCode() + ycPhase.getWorkGroupNumber());
                        if (ObjectUtils.isNotEmpty(ycErpDateMaps)) {
                            Map<String, Object> ycErpPhase = ycErpDateMaps.get(0);
                            ycErpPhaseReport.setWorkPlace(ycPhase.getWorkGroupNumber());
                            ycErpPhaseReport.setOpSeq(ycErpPhase.get("seq").toString());
                            ycErpPhaseReport.setOpCode(ycErpPhase.get("op_code").toString());
                            ycErpPhaseReport.setOpName(ycErpPhase.get("op_name").toString());
                            ycErpPhaseReport.setOp(ycErpPhase.get("op").toString());
                            reportErpMapper.insert(ycErpPhaseReport);
                        }
                    }
                }

                reportErpMapper.insert(erpPhaseReport);
                //更新报工记录
                workRecordMapper.lambdaUpdate().set(WorkRecord::getErpState, 2)
                        .in(WorkRecord::getId, recordIds).update();
            } catch (Exception e) {
                //更新报工记录
                workRecordMapper.lambdaUpdate().set(WorkRecord::getErpState, 3)
                        .in(WorkRecord::getId, recordIds).update();
                System.out.println(e.getMessage());
            }
        }
    }
    /**
     * @Description: 工序链出现多工序
     *
     * @author: hejiahui
     * @since: 2025/4/23 13:46
     */
    private Map<String, Object> getByPhaseSeq(List<Map<String, Object>> erpDateMaps, Integer phaseSeq) {
        Map<Integer, List<Map<String, Object>>> seqMap = erpDateMaps.stream().collect(Collectors.groupingBy(e -> Integer.parseInt(e.get("seq").toString())));
        List<Integer> listSeq = seqMap.keySet().stream().sorted(Comparator.comparing(Integer::intValue)).collect(Collectors.toList());
        final Integer i = listSeq.get(phaseSeq);
        if (seqMap.containsKey(i)) {
            return seqMap.get(i).get(0);
        } else {
            return erpDateMaps.get(0);
        }
    }

    /**
     * @Description: 回传erp
     *
     * @author: hejiahui
     * @since: 2024/10/9 17:04
     */
    public void reportErpDate(String startTime, String endTime) {
        List<String> conSplit = new ArrayList<>();
        if (StringUtils.isNotBlank(sendErpFilter)) {
            conSplit = Arrays.asList(sendErpFilter.split(","));
        }
        //获取不回传数据
        QueryWrapper<NoreportErpConfig> noreportErpConfigWrapper = new QueryWrapper<>();
        noreportErpConfigWrapper.eq( "deleted", 0);
        List<NoreportErpConfig> noreportErpConfigs = noreportErpConfigMapper.selectList(noreportErpConfigWrapper);
        //获取回传记录
        LambdaQueryChainWrapper<ReportErpReply> betweenWrapper = reportErpMapper.lambdaQuery()
                .notIn(ObjectUtils.isNotEmpty(conSplit), ReportErpReply::getOrderCode, conSplit)
                .eq(ReportErpReply::getFlag, -1)
                .between(ReportErpReply::getUpdateDate, startTime, endTime);
        if (ObjectUtils.isNotEmpty(noreportErpConfigs)) {
            for (NoreportErpConfig noreportErpConfig : noreportErpConfigs) {
                betweenWrapper.not(e -> {
                    LambdaQueryWrapper<ReportErpReply> wrap = e
                            .eq(ReportErpReply::getOrderCode, noreportErpConfig.getOrderCode())
                            .eq(StringUtils.isNotBlank(noreportErpConfig.getWorkOrderCode()), ReportErpReply::getWorkOrderCode, noreportErpConfig.getWorkOrderCode())
                            .eq(StringUtils.isNotBlank(noreportErpConfig.getPhase()), ReportErpReply::getPhase, noreportErpConfig.getPhase());
                });
            }
        }
        List<ReportErpReply> reportErpLogList = betweenWrapper.list();
        reportErpLogList = reportErpLogList.stream().sorted(Comparator.comparing(ReportErpReply::getOpSeq)).collect(Collectors.toList());
        //回传erp
        for (ReportErpReply reportErpReply : reportErpLogList) {
            try {
                //只能一个一个传，批量传的话累积数量会不准
                this.reportToErp(reportErpReply);
            }catch (Exception e){
                reportErpReply.setFlag(0);
                reportErpReply.setErrorLog(e.getMessage());
                reportErpReply.setUpdateDate(DateUtil.date().toString());
                reportErpMapper.updateById(reportErpReply);
            }
        }
    }
    /**
     * @Description: 根据id回传erp
     *
     * @author: hejiahui
     * @since: 2024/10/10 16:15
     */
    public void rereportErpDate(List<Integer> ids) {
        //获取回传记录
        List<ReportErpReply> reportErpLogList = reportErpMapper.selectBatchIds(ids);
        reportErpLogList = reportErpLogList.stream().sorted(Comparator.comparing(ReportErpReply::getOpSeq)).collect(Collectors.toList());
        //回传erp
        for (ReportErpReply reportErpReply : reportErpLogList) {
            try {
                //只能一个一个传，批量传的话累积数量会不准
                this.reportToErp(reportErpReply);
            }catch (Exception e){
                reportErpReply.setFlag(0);
                reportErpReply.setErrorLog(e.getMessage());
                reportErpReply.setUpdateDate(DateUtil.date().toString());
                reportErpMapper.updateById(reportErpReply);
            }
        }
    }
    /**
     * @Description: 每天重新回传近5天失败少于5次的报工记录
     *
     * @author: hejiahui
     * @since: 2024/10/15 14:09
     */
    public void dynamicReportToErp() {
        List<String> conSplit = new ArrayList<>();
        if (StringUtils.isNotBlank(sendErpFilter)) {
            conSplit = Arrays.asList(sendErpFilter.split(","));
        }
        //获取回传记录
        String start = DateUtil.date().offset(DateField.DAY_OF_MONTH,-5).toString("yyyy-MM-dd") + " 00:00:00";
        String end = DateUtil.date().toString( "yyyy-MM-dd HH:mm:ss");
        List<ReportErpReply> reportErpLogList = reportErpMapper.lambdaQuery()
                .notIn(ObjectUtils.isNotEmpty(conSplit),  ReportErpReply::getOrderCode,conSplit)
                .ne(ReportErpReply::getFlag,1)
                .le(ReportErpReply::getReportTimes, 5)
                .between(ReportErpReply::getUpdateDate, start, end)
                .ne(ReportErpReply::getPhase,"PT")
                .ne(ReportErpReply::getOkQty,0)
                .list();
        //过滤已关闭订单
        List<ReportErpReply> colseList = reportErpLogList.stream().filter(e -> e.getErrorLog().contains("此工单已关闭")).collect(Collectors.toList());
        for (ReportErpReply clost : colseList) {
            clost.setReportTimes(11);
            reportErpMapper.updateById(clost);
        }
        //回传erp
        List<ReportErpReply> openList = reportErpLogList.stream().filter(e -> !e.getErrorLog().contains("此工单已关闭")).collect(Collectors.toList());
        openList = openList.stream().sorted(Comparator.comparing(ReportErpReply::getOpSeq)).collect(Collectors.toList());
        //10个一组进行回传，避免时间太长
        for (int i = 0; i < openList.size(); i++) {
            List<ReportErpReply> subList = openList.subList(i * 10, Math.min(i * 10 + 10, openList.size()));
            try {
                //批量回传接口
                this.reportMoreToErp(subList);
            }catch (Exception e){
                for (ReportErpReply reportErpReply : subList) {
                    reportErpReply.setFlag(0);
                    reportErpReply.setErrorLog(e.getMessage());
                    reportErpReply.setUpdateDate(DateUtil.date().toString());
                    reportErpMapper.updateById(reportErpReply);
                }
            }
        }
//        for (ReportErpReply reportErpReply : openList) {
//            try {
//                //只能一个一个传，批量传的话累积数量会不准
//                this.reportToErp(reportErpReply);
//            }catch (Exception e){
//                reportErpReply.setFlag(0);
//                reportErpReply.setErrorLog(e.getMessage());
//                reportErpReply.setUpdateDate(DateUtil.date().toString());
//            }
//        }
    }

    private void reportMoreToErp(List<ReportErpReply> subList)  throws Exception{
        String token = getERPToken();
        List<ErpPhaseReport> erpPhaseReports = new ArrayList<>();

        for (ReportErpReply reportErpLog : subList) {
            //计算累积数量
            List<ReportErpReply> successList = reportErpMapper.lambdaQuery().eq(ReportErpReply::getOkId, "Y")
                    .eq(ReportErpReply::getOrderCode, reportErpLog.getOrderCode())
                    .eq(ReportErpReply::getTaskCode, reportErpLog.getTaskCode())
                    .eq(ReportErpReply::getWorkOrderCode, reportErpLog.getWorkOrderCode())
                    .eq(ReportErpReply::getPlmid, reportErpLog.getPlmid())
                    .eq(ReportErpReply::getMaterialCode, reportErpLog.getMaterialCode())
                    .eq(ReportErpReply::getPhase, reportErpLog.getPhase())
                    .eq(ReportErpReply::getWorkOrderParent, reportErpLog.getWorkOrderParent())
                    .eq(ReportErpReply::getOpCode, reportErpLog.getOpCode()).list();
            Integer addQty = reportErpLog.getOkQty();
            if (ObjectUtils.isNotEmpty(successList)) {
                addQty = addQty + successList.stream().mapToInt(ReportErpReply::getOkQty).sum();
            }
            reportErpLog.setAddQty(addQty);
            //回传次数+1
            Integer reportTimes = reportErpLog.getReportTimes();
            reportTimes++;
            reportErpLog.setReportTimes(reportTimes);
            //转换成回传erp实体
            ErpPhaseReport erpPhaseReport = new ErpPhaseReport();
            BeanUtil.copyProperties(reportErpLog, erpPhaseReport);
            //判断是否超出
            int orderCnt = Integer.MAX_VALUE;
            if(ObjectUtils.isNotEmpty(reportErpLog.getOrderCnt())){
                orderCnt = reportErpLog.getOrderCnt();
            }
            if (erpPhaseReport.getAddQty() > orderCnt) {
                Integer addCnt = erpPhaseReport.getAddQty();
                erpPhaseReport.setOkQty(erpPhaseReport.getOkQty() - (addCnt - orderCnt));
                erpPhaseReport.setAddQty(orderCnt);
            }
            erpPhaseReport.setMesId(reportErpLog.getId());
            erpPhaseReports.add(erpPhaseReport);
        }

        Map<String, Object> map = erpApiClient.mesRepoFeedback(token, erpPhaseReports);
        if (ObjectUtils.isEmpty(map)) {
            throw new Exception("回传erp接口调用失败！");
        }

        if (!(Boolean) map.get("success")) {
            throw new Exception((String) map.get("message"));
        } else {
            //回传成功则将okid设为Y进行重传
            for (ErpPhaseReport erpPhaseReport : erpPhaseReports) {
                erpPhaseReport.setOkId("Y");
            }
            map = erpApiClient.mesRepoFeedback(token, erpPhaseReports);
            if ((Boolean) map.get("success")) {
                for (ReportErpReply reportErpLog : subList) {
                    reportErpLog.setFlag(1);
                    reportErpLog.setOkId("Y");
                    reportErpLog.setUpdateDate(DateUtil.date().toString());
                    reportErpMapper.updateById(reportErpLog);
                }
            } else {
                throw new Exception((String) map.get("message"));
            }
        }
    }

    /**
     * @Description: 回传erp
     *
     * @author: hejiahui
     * @since: 2024/10/9 17:04
     */
    private void reportToErp(ReportErpReply reportErpLog) throws Exception {
        String token = getERPToken();
        List<ErpPhaseReport> erpPhaseReports = new ArrayList<>();

        //库检工序不回传
        if (reportErpLog.getPhase().equals("KJ") || reportErpLog.getPhase().equals("PT")) {
            reportErpLog.setReportTimes(1);
            reportErpLog.setFlag(1);
            reportErpLog.setOkId("Y");
            reportErpLog.setUpdateDate(DateUtil.date().toString());
            reportErpMapper.updateById(reportErpLog);
            return;
        }
        //三大件大组件顶级物料的最后一道工序不回传
        QueryWrapper<?> topWrapper = new QueryWrapper<>();
        topWrapper.eq("ord.construct_no",reportErpLog.getOrderCode());
        topWrapper.eq("ord.plm_id", reportErpLog.getPlmid());
        List<Map<String, Object>> topAssembly = reportErpMapper.getTopAssembly(topWrapper);
        if (ObjectUtils.isNotEmpty(topAssembly)) {
            final String[] phaseArrays = topAssembly.get(0).get("workChain").toString().split("-");
            if (phaseArrays[phaseArrays.length - 1].equals(reportErpLog.getPhase())) {
                reportErpLog.setReportTimes(1);
                reportErpLog.setFlag(1);
                reportErpLog.setOkId("Y");
                reportErpLog.setUpdateDate(DateUtil.date().toString());
                reportErpMapper.updateById(reportErpLog);
                return;
            }
        }

        //计算累积数量
        List<ReportErpReply> successList = reportErpMapper.lambdaQuery().eq(ReportErpReply::getOkId, "Y")
                .eq(ReportErpReply::getOrderCode, reportErpLog.getOrderCode())
                .eq(ReportErpReply::getTaskCode, reportErpLog.getTaskCode())
                .eq(ReportErpReply::getWorkOrderCode, reportErpLog.getWorkOrderCode())
                .eq(ReportErpReply::getPlmid, reportErpLog.getPlmid())
                .eq(ReportErpReply::getMaterialCode, reportErpLog.getMaterialCode())
                .eq(ReportErpReply::getPhase, reportErpLog.getPhase())
                .eq(ReportErpReply::getWorkOrderParent, reportErpLog.getWorkOrderParent())
                .eq(ReportErpReply::getOpCode, reportErpLog.getOpCode())
                .eq(ReportErpReply::getWoId, reportErpLog.getWoId())
                .list();
        Integer addQty = reportErpLog.getOkQty();
        if (ObjectUtils.isNotEmpty(successList)) {
            addQty = addQty + successList.stream().mapToInt(ReportErpReply::getOkQty).sum();
        }
        reportErpLog.setAddQty(addQty);
        //回传次数+1
        Integer reportTimes = reportErpLog.getReportTimes();
        reportTimes++;
        reportErpLog.setReportTimes(reportTimes);
        //转换成回传erp实体
        ErpPhaseReport erpPhaseReport = new ErpPhaseReport();
        BeanUtil.copyProperties(reportErpLog, erpPhaseReport);
        //判断是否超出
        int orderCnt = Integer.MAX_VALUE;
        if(ObjectUtils.isNotEmpty(reportErpLog.getOrderCnt())){
            orderCnt = reportErpLog.getOrderCnt();
        }
        if (erpPhaseReport.getAddQty() > orderCnt) {
            Integer addCnt = erpPhaseReport.getAddQty();
            int lostCnt = erpPhaseReport.getOkQty() - (addCnt - orderCnt);
            if (lostCnt <= 0) {
                reportErpLog.setOkQty(lostCnt);
                reportErpLog.setAddQty(orderCnt);
                throw new Exception("报工数量超出订单数量！");
            }
            erpPhaseReport.setOkQty(lostCnt);
            erpPhaseReport.setAddQty(orderCnt);
        }
        reportErpLog.setOkQty(erpPhaseReport.getOkQty());
        reportErpLog.setAddQty(erpPhaseReport.getAddQty());
        erpPhaseReport.setMesId(reportErpLog.getId());
        erpPhaseReports.add(erpPhaseReport);
        Map<String, Object> map = erpApiClient.mesRepoFeedback(token, erpPhaseReports);
//        Map<String, Object> map = new HashMap<>();
//        map.put("success", true);
        if (ObjectUtils.isEmpty(map)) {
            throw new Exception("回传erp接口调用失败！");
        }

        if (!(Boolean) map.get("success")) {
            throw new Exception((String) map.get("message"));
        } else {
            //回传成功则将okid设为Y进行重传
            erpPhaseReport.setOkId("Y");
            map = erpApiClient.mesRepoFeedback(token, erpPhaseReports);
//            map.put("success", true);
            if ((Boolean) map.get("success")) {
                reportErpLog.setFlag(1);
                reportErpLog.setOkId("Y");
                reportErpLog.setUpdateDate(DateUtil.date().toString());
                reportErpMapper.updateById(reportErpLog);
            } else {
                throw new Exception((String) map.get("message"));
            }
        }
    }
    /**
     * 生成erp的token
     *
     * @author: hejiahui
     * @since: 2023/2/9 14:12
     */
    public String getERPToken() throws Exception {
        String str = DateUtil.date().toDateStr() + "|jgjmes";
        String token = MD5.md5(str);
        return token;
    }
    /**
     * 分页查询
     *
     * @param reportErpLogQureyDto 筛选条件
     * @return 查询结果
     */
    public IPage<SysReportErpLogVo> getReportErpLogpage(ReportErpLogQureyDto reportErpLogQureyDto) {
        IPage<ReportErpReply> page = new Page<>(reportErpLogQureyDto.getPage(), reportErpLogQureyDto.getSize());
        QueryWrapper<ReportErpReply> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(reportErpLogQureyDto.getPlmid()),"plmid" , reportErpLogQureyDto.getPlmid());
        queryWrapper.like(StringUtils.isNotBlank(reportErpLogQureyDto.getMaterialCode()),"material_code" , reportErpLogQureyDto.getMaterialCode());
        queryWrapper.like(StringUtils.isNotBlank(reportErpLogQureyDto.getOrderCode()),"order_code" , reportErpLogQureyDto.getOrderCode());
        queryWrapper.like(StringUtils.isNotBlank(reportErpLogQureyDto.getWorkOrderCode()),"work_order_code" , reportErpLogQureyDto.getWorkOrderCode() );
        queryWrapper.like(StringUtils.isNotBlank(reportErpLogQureyDto.getPhase()),"phase" , reportErpLogQureyDto.getPhase() );
        queryWrapper.like(StringUtils.isNotBlank(reportErpLogQureyDto.getPartName()),"part_name" , reportErpLogQureyDto.getPartName() );
        queryWrapper.like(StringUtils.isNotBlank(reportErpLogQureyDto.getTaskCode()),"task_code" , reportErpLogQureyDto.getTaskCode() );
        queryWrapper.eq(StringUtils.isNotBlank(reportErpLogQureyDto.getOkId()),"ok_id" , reportErpLogQureyDto.getOkId() );
        if (StringUtils.isBlank(reportErpLogQureyDto.getStartTime())) {
            reportErpLogQureyDto.setStartTime(DateUtil.date().offset(DateField.DAY_OF_MONTH,-7).toString());
        }
        if (StringUtils.isBlank(reportErpLogQureyDto.getEndTime())) {
            reportErpLogQureyDto.setEndTime(DateUtil.date().offset(DateField.DAY_OF_MONTH,7).toString());
        }
        queryWrapper.ge("create_date" , reportErpLogQureyDto.getStartTime());
        queryWrapper.le("create_date" , reportErpLogQureyDto.getEndTime() );
        if (ObjectUtils.isNotEmpty(reportErpLogQureyDto.getSortOkQty())) {
            if (reportErpLogQureyDto.getSortOkQty() == 1) {
                queryWrapper.orderByAsc("ok_qty");
            } else if (reportErpLogQureyDto.getSortOkQty() == 2) {
                queryWrapper.orderByDesc("ok_qty");
            }
        }
        IPage<ReportErpReply> tbThirdReportErpLogIPage = reportErpMapper.selectPage(page, queryWrapper);
        IPage<SysReportErpLogVo> result = new Page<>();
        BeanUtil.copyProperties(tbThirdReportErpLogIPage, result);
        List<ReportErpReply> records = tbThirdReportErpLogIPage.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return result;
        }
        //获取订单数量
        Set<String>  orderCodeSet = records.stream().map(e -> e.getOrderCode()).collect(Collectors.toSet());
        Set<String> woNoList = records.stream().map(e -> e.getWorkOrderCode()).collect(Collectors.toSet());
        Set<String> pWoNoList = records.stream().map(e -> e.getWorkOrderParent()).collect(Collectors.toSet());
        Set<String> plmidSet = records.stream().map(e -> e.getPlmid()).collect(Collectors.toSet());
        Set<Integer> wpSet = records.stream().map(e -> {
            return PkgUtils.rollBack(e.getTaskCode());
        }).collect(Collectors.toSet());
        QueryWrapper<?> orderQuery = new QueryWrapper<>();
        orderQuery.in("ord.construct_no", orderCodeSet);
        orderQuery.in("aword.work_order_code", woNoList);
        orderQuery.in(ObjectUtils.isNotEmpty(pWoNoList),"pbom.work_order_code", pWoNoList);
        orderQuery.in("aord.seq", wpSet);
        orderQuery.in("bom.plm_id", plmidSet);
        List<Map<String, Object>> orderCntList = reportErpMapper.getOrderCntList(orderQuery);
        Map<String, List<Map<String, Object>>> mapList = orderCntList.stream().collect(Collectors.groupingBy(e -> e.get("construct_no").toString() +
                e.get("seq") + e.get("woNo") + e.get("pWoNo") + e.get("plm_id")));
        List<SysReportErpLogVo> sysReportErpLogVoList = new ArrayList<>();
        for (ReportErpReply record : records) {
            SysReportErpLogVo vo = new SysReportErpLogVo();
            BeanUtil.copyProperties(record, vo);
            List<Map<String, Object>> cntList = mapList.get(record.getOrderCode() + PkgUtils.rollBack(record.getTaskCode()) + record.getWorkOrderCode()
                    + record.getWorkOrderParent() + record.getPlmid());
            if (ObjectUtils.isNotEmpty(cntList)) {
                Integer totalCnt = new BigDecimal(cntList.get(0).get("totalCnt").toString()).intValue();
                vo.setOrderCount(totalCnt);
            }
            sysReportErpLogVoList.add(vo);
        }
        result.setRecords(sysReportErpLogVoList);
        return result;
    }
    /**
     * @Description: 更新数据
     *
     * @author: hejiahui
     * @since: 2024/10/15 11:26
     */
    public void reportErpLogUpdate(ReportErpLogUpdateDto dto) {
        ReportErpReply reportErpLog = new ReportErpReply();
        BeanUtil.copyProperties(dto, reportErpLog);
        reportErpMapper.updateById(reportErpLog);
    }
    /**
     * 删除数据
     *
     * @param id 主键
     * @return 删除是否成功
     */
    public void deleteById(Integer id) {
        reportErpMapper.lambdaUpdate().set(ReportErpReply::getDeleted, 1).eq(ReportErpReply::getId, id).update();
    }
    /**
     * @Description: 根据分拣生成前序工序
     *
     * @author: hejiahui
     * @since: 2023/10/10 10:14
     */
    public void buildBeforePhase(String constructNo) {
        List<ReportErpReply> reportErpReplies = reportErpMapper.lambdaQuery().eq(ReportErpReply::getOrderCode, constructNo).list();
        Map<String, List<ReportErpReply>> pkgPLmMap = reportErpReplies.stream().collect(Collectors.groupingBy(e -> e.getTaskCode() + "," + e.getPlmid() + "," + e.getWorkOrderParent()));
        List<ReportErpReply> needBuildList = new ArrayList<>();
        for (String key : pkgPLmMap.keySet()) {
            List<ReportErpReply> list = pkgPLmMap.get(key);
            List<ReportErpReply> beforeList = list.stream().filter(e -> e.getPhase().equals("YC") || e.getPhase().equals("JG") || e.getPhase().equals("HG")).collect(Collectors.toList());
            if (ObjectUtils.isEmpty(beforeList)) {
                needBuildList.add(list.stream().filter(e -> e.getPhase().equals("FJ")).collect(Collectors.toList()).get(0));
            }
        }
        if (ObjectUtils.isEmpty(needBuildList)) {
            return;
        }
        Set<Integer> woIdSet = needBuildList.stream().map(e -> e.getWoId()).collect(Collectors.toSet());
        //获取detail数据
        List<ApsWorkDetail> apsWorkDetailList = apsWorkDetailMapper.lambdaQuery().in(ApsWorkDetail::getApsWorkOrderId, woIdSet).list();
        Map<Integer, List<ApsWorkDetail>> woIdMap = apsWorkDetailList.stream().collect(Collectors.groupingBy(e -> e.getApsWorkOrderId()));
        //获取erp数据
        Set<String> orderCodeSet = needBuildList.stream().map(e -> e.getOrderCode()).collect(Collectors.toSet());
        Set<String> materialCodeList = needBuildList.stream().map(e -> e.getMaterialCode()).collect(Collectors.toSet());
        QueryWrapper<?> erpWrapper = new QueryWrapper<>();
        erpWrapper.in("detail.order_code", orderCodeSet);
        erpWrapper.in("detail.material_code", materialCodeList);
        List<Map<String, Object>> erpDateMapList = reportErpMapper.getErpPhaseMap(erpWrapper);
        Map<String, List<Map<String, Object>>> erpDateMap = erpDateMapList.stream().collect(Collectors.groupingBy(e -> e.get("order_code").toString() + e.get("material_code")
                + e.get("mes_work_phase") + e.get("mes_work_center")));
        for (ReportErpReply reportErpReply : needBuildList){
            //生成切割工序
            List<ApsWorkDetail> thisDetails = woIdMap.get(reportErpReply.getWoId());
            ApsWorkDetail FjDetail = thisDetails.stream().filter(e -> e.getPhaseCode().equals(reportErpReply.getPhase())).collect(Collectors.toList()).get(0);
            ApsWorkDetail cuttingDetail = thisDetails.stream().filter(e -> e.getPhaseSeq().equals(FjDetail.getPhaseSeq() - 1)).collect(Collectors.toList()).get(0);
            Map<String, Object> cuttingErpMap = erpDateMap.get(reportErpReply.getOrderCode() + reportErpReply.getMaterialCode() + cuttingDetail.getPhaseCode() + cuttingDetail.getGroupCode()).get(0);
            ReportErpReply cuttingReport = new ReportErpReply();
            BeanUtil.copyProperties(reportErpReply, cuttingReport);
            cuttingReport.setOkQty(FjDetail.getTotalCount().intValue());
            cuttingReport.setOpSeq(cuttingErpMap.get("seq").toString());
            cuttingReport.setOpCode(cuttingErpMap.get("op_code").toString());
            cuttingReport.setOpName(cuttingErpMap.get("op_name").toString());
            cuttingReport.setOp(cuttingErpMap.get("op").toString());
            cuttingReport.setPhase(cuttingDetail.getPhaseCode());
            cuttingReport.setWorkPlace(cuttingDetail.getGroupCode());
            cuttingReport.setOkId("N");
            reportErpMapper.insert(cuttingReport);
            //生成YC工序
            Map<String, Object> ycErpMap = erpDateMap.get(reportErpReply.getOrderCode() + reportErpReply.getMaterialCode() + "YC" + "1-1_SC_GBCL_01").get(0);
            ReportErpReply ycReport = new ReportErpReply();
            BeanUtil.copyProperties(reportErpReply, ycReport);
            ycReport.setOkQty(FjDetail.getTotalCount().intValue());
            ycReport.setOpSeq(ycErpMap.get("seq").toString());
            ycReport.setOpCode(ycErpMap.get("op_code").toString());
            ycReport.setOpName(ycErpMap.get("op_name").toString());
            ycReport.setOp(ycErpMap.get("op").toString());
            ycReport.setPhase("YC");
            ycReport.setWorkPlace("1-1_SC_GBCL_01");
            ycReport.setOkId("N");
            reportErpMapper.insert(ycReport);
        }
    }
    /**
     * @Description: 自动生成缺失的预处理记录
     *
     * @author: hejiahui
     * @since: 2025/3/15 8:28
     */
    public void generateYcReport(String constructNo) {
        if (StringUtils.isBlank(constructNo)) {
            return;
        }
        //获取aps中YC工序零件数量
        QueryWrapper<?> apsYcWrapper = new QueryWrapper<>();
        apsYcWrapper.eq("ord.order_code", constructNo);
        apsYcWrapper.like("bom.work_chain", "YC");
        apsYcWrapper.eq("det.phase_code", "YC");
        List<Map<String,Object>> apsYcList = reportErpMapper.getApsYcList(apsYcWrapper);
        if (ObjectUtils.isEmpty(apsYcList)) {
            return;
        }
        Map<String, List<Map<String, Object>>> apsYcMap = apsYcList.stream().collect(Collectors.groupingBy(e -> e.get("work_order_code").toString() + e.get("plm").toString()));
        //获取回传erp已生成的YC数据
        QueryWrapper<?> erpYcWrapper = new QueryWrapper<>();
        erpYcWrapper.eq("order_code", constructNo);
        erpYcWrapper.like("phase", "YC");
        List<Map<String,Object>> erpYcList = reportErpMapper.getErpYcList(erpYcWrapper);
        Map<String, List<Map<String, Object>>> erpYcMap = new HashMap<>();
        if (ObjectUtils.isNotEmpty(erpYcList)) {
            erpYcMap = erpYcList.stream().collect(Collectors.groupingBy(e -> e.get("work_order_code").toString() + e.get("plmid").toString()));
        }
        //补充缺失的YC回传数据
        List<Map<String, Object>> addList = new ArrayList<>();
        for (String key : erpYcMap.keySet()) {
            List<Map<String, Object>> erpList = erpYcMap.get(key);
            List<Map<String, Object>> apsList = apsYcMap.get(key);
            if (ObjectUtils.isNotEmpty(apsList)) {
                final int erpCnt = Integer.parseInt(erpList.get(0).get("totalCnt").toString());
                final int apsCnt = Integer.parseInt(apsList.get(0).get("phaseCnt").toString());
                if (erpCnt < apsCnt) {
                    Map<String, Object> addMap = new HashMap<>();
                    addMap.put("work_order_code", erpList.get(0).get("work_order_code"));
                    addMap.put("plmid", erpList.get(0).get("plmid"));
                    addMap.put("addCnt", apsCnt - erpCnt);
                    addList.add(addMap);
                }
            }
        }
        for (Map<String, Object> addReport : addList) {
            LambdaQueryWrapper<ReportErpReply> reportWrapper = new LambdaQueryWrapper<>();
            reportWrapper.eq(ReportErpReply::getOrderCode, constructNo);
            reportWrapper.eq(ReportErpReply::getWorkOrderCode, addReport.get("work_order_code"));
            reportWrapper.eq(ReportErpReply::getPlmid, addReport.get("plmid"));
            reportWrapper.eq(ReportErpReply::getPhase, "YC");
            reportWrapper.last("limit 1");
            ReportErpReply reportErpReplies = reportErpMapper.selectList(reportWrapper).get(0);
            reportErpReplies.setId(null);
            reportErpReplies.setFlag(0);
            reportErpReplies.setOkId("N");
            reportErpReplies.setReportTimes(0);
            reportErpReplies.setOkQty(Integer.parseInt(addReport.get("addCnt").toString()));
            reportErpMapper.insert(reportErpReplies);
        }
    }
}
